/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许，不可做商业用途！
 *
 * 版权所有，侵权必究！
 */
package com.yami.shop.distribution.common.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.PhoneUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yami.shop.common.util.PrincipalUtil;
import com.yami.shop.distribution.common.constants.*;
import com.yami.shop.distribution.common.dao.*;
import com.yami.shop.distribution.common.dto.AchievementDataDto;
import com.yami.shop.distribution.common.dto.DistributionUserAchievementDataDto;
import com.yami.shop.distribution.common.dto.DistributionUserSimpleDto;
import com.yami.shop.distribution.common.model.*;
import com.yami.shop.distribution.common.param.RangeTimeParam;
import com.yami.shop.distribution.common.param.UpdateDistributionUserParam;
import com.yami.shop.distribution.common.service.DistributionUserService;
import com.yami.shop.distribution.common.service.DistributionUserWalletBillService;
import com.yami.shop.distribution.common.service.DistributionUserWalletService;
import com.yami.shop.distribution.common.vo.DistributionUserInfoVO;
import com.yami.shop.distribution.common.vo.DistributionUserVO;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author lgh on 2019/04/01.
 */
@Service
@RequiredArgsConstructor
public class DistributionUserServiceImpl extends ServiceImpl<DistributionUserMapper, DistributionUser> implements DistributionUserService {

    @Value("${yami.expose.operation.auth:}")
    private Boolean permission;

    private final DistributionUserMapper distributionUserMapper;

    private final DistributionUserBanMapper distributionUserBanMapper;

    private final DistributionUserBindMapper distributionUserBindMapper;

    private final DistributionAuditingMapper distributionAuditingMapper;

    private final DistributionUserWalletService distributionUserWalletService;

    private final DistributionProdBindMapper distributionProdBindMapper;

    private final DistributionUserIncomeMapper distributionUserIncomeMapper;

    private final DistributionUserWalletMapper distributionUserWalletMapper;

    private final DistributionWithdrawCashMapper distributionWithdrawCashMapper;

    private final DistributionUserWalletBillService distributionUserWalletBillService;

    @Override
    @Cacheable(cacheNames = "distribution_user", key = "#shopId + ':' + #userId")
    public DistributionUser getByUserIdAndShopId(String userId, Long shopId) {
        return distributionUserMapper.selectOne(new LambdaQueryWrapper<DistributionUser>().eq(DistributionUser::getUserId, userId).eq(DistributionUser::getShopId, shopId));
    }

    @Override
    @CacheEvict(cacheNames = "distribution_user", key = "#shopId + ':' + #userId")
    public void removeCacheByUserIdAndShopId(String userId, Long shopId) {

    }

    @Override
    public AchievementDataDto getAchievementDataDtoById(Long id) {
        return distributionUserMapper.getAchievementDataDtoById(id);
    }

    @Override
    public DistributionUserAchievementDataDto getDistributionUserLevelAchievementDataByDistributionUserId(Long distributionUserId) {
        return distributionUserMapper.getLevelDistributionUserAchievementDataByDistributionUserId(distributionUserId);
    }

    @Override
    public IPage<DistributionUser> distributionUserPage(Page page, DistributionUser distributionUser, RangeTimeParam rangeTimeParam
            , String mobile, String parentMobile, Integer sortChange, Integer state) {
        IPage<DistributionUser> userPage = distributionUserMapper.distributionUserPage(page, distributionUser, rangeTimeParam, mobile, parentMobile, sortChange, state);
        if (BooleanUtil.isFalse(permission)) {
            for (DistributionUser record : userPage.getRecords()) {
                if (StrUtil.isNotBlank(record.getUserMobile())) {
                    record.setUserMobile(PhoneUtil.hideBetween(record.getUserMobile()).toString());
                }
                if (PrincipalUtil.isMobile(record.getNickName())) {
                    record.setNickName(PhoneUtil.hideBetween(record.getNickName()).toString());
                }
                DistributionUserVO parent = record.getParentDistributionUser();
                if (Objects.nonNull(parent)) {
                    parent.setUserMobile(PhoneUtil.hideBetween(parent.getUserMobile()).toString());
                    if (PrincipalUtil.isMobile(parent.getNickName())) {
                        parent.setNickName(PhoneUtil.hideBetween(parent.getNickName()).toString());
                    }
                }
            }
        }
        return userPage;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateSelectiveAndInsertDistributionUserBan(UpdateDistributionUserParam param, Long modifier) {
        //创建ban对象，插入数据后修改分销员状态
        DistributionUserBan distributionUserBan = new DistributionUserBan();
        distributionUserBan.setDistributionUserId(param.getDistributionUserId());
        distributionUserBan.setRemarks(param.getRemarks());
        distributionUserBan.setBanReason(param.getBanReason());
        distributionUserBan.setState(param.getState());
        distributionUserBan.setModifier(modifier);
        distributionUserBan.setUpdateTime(new Date());
        distributionUserBanMapper.insert(distributionUserBan);
        DistributionUser distributionUserDb = getById(param.getDistributionUserId());

        // 如果之前是暂时封禁[2]状态，现在改成正常状态[1],恢复以前的没有被抢的绑定用户。
        if (distributionUserDb.getState() == DistributionUserStateEnum.BAN.getValue() && param.getState() == DistributionUserStateEnum.NORMAL.getValue()) {
            List<DistributionUserBind> userBindList = distributionUserBindMapper.selectList(new LambdaQueryWrapper<DistributionUserBind>()
                    .eq(DistributionUserBind::getDistributionUserId, param.getDistributionUserId())
                    .eq(DistributionUserBind::getState, -1)
                    .eq(DistributionUserBind::getInvalidReason, 3));
            if (CollectionUtil.isNotEmpty(userBindList)) {
                // 查询出所有暂时封禁但已经被抢的用户
                List<String> userIds = distributionUserBindMapper.selectClearUserByDistributionUserId(userBindList);
                if (CollectionUtil.isNotEmpty(userIds)) {
                    userBindList = userBindList.stream().filter(userBind -> !userIds.contains(userBind.getUserId())).collect(Collectors.toList());
                }
                if (CollectionUtil.isNotEmpty(userBindList)) {
                    // 将没有被抢的，失效的绑定用户设为正常。
                    distributionUserBindMapper.recoveryRelationsByUserId(userBindList);
                }
            }
        }

        // 更新分销员状态
        DistributionUser distributionUser = new DistributionUser();
        distributionUser.setDistributionUserId(param.getDistributionUserId());
        distributionUser.setState(param.getState());
        distributionUser.setBindTime(distributionUserDb.getBindTime());
        distributionUser.setLevel(distributionUserDb.getLevel());
        //如果是暂时封禁[2]或永久封禁[-1]
        if (param.getState() == DistributionUserStateEnum.BAN.getValue() || param.getState() == DistributionUserStateEnum.PER_BAN.getValue()) {
            distributionUser.setStateRecord(param.getState());
            //将绑定的用户设为失效
            distributionUserBindMapper.updateStateAndReasonByDistributionUserId(param.getDistributionUserId(), -1);
            DistributionUser distributionUser1 = distributionUserMapper.selectById(param.getDistributionUserId());
            distributionUserBindMapper.updateStateAndReasonByUserId(distributionUser1.getUserId(), -1);
            //将商品分享记录设为失效
            distributionProdBindMapper.updateStateByDistributionUserId(param.getDistributionUserId(), -1);
            //判断是否为永久封禁
            if (param.getState() == DistributionUserStateEnum.PER_BAN.getValue()) {
                //将正在处理中的佣金订单冻结
                updateStateByDistributionUserId(param.getDistributionUserId());
                //将tz_distribution_user_wallet累计收益改为0
                updateAmountByDistributionUserId(param.getDistributionUserId());
                //将tz_distribution_user上级id清空[清空该被永久封禁的分销员的下级关系]
                distributionUserMapper.updateParentIdById(param.getDistributionUserId());
                //提现记录为申请中的变为拒绝提现
                distributionWithdrawCashMapper.updateUserByDistributionUserId(param.getDistributionUserId());
                //等级恢复为1
                distributionUser.setLevel(1);
            }
        }
        // 如果恢复成正常状态就不需要记录之前的状态了
        if (param.getState() == DistributionUserStateEnum.NORMAL.getValue()) {
            distributionUser.setStateRecord(null);
        }
        distributionUserMapper.updateStatusById(distributionUser);
    }

    /**
     * 永久封禁后冻结所有收入订单和上级间推收入
     *
     * @param id
     */
//    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    void updateStateByDistributionUserId(Long id) {
        distributionUserIncomeMapper.updateStateByDistributionUserId(id, -1);
        DistributionUser distributionUser = distributionUserMapper.selectById(id);
        if (distributionUser.getParentId() == null) {
            log.debug("没有上级分销员");
            return;
        }
        List<DistributionUserIncome> distributionUserIncomes = distributionUserIncomeMapper.selectList(new LambdaQueryWrapper<DistributionUserIncome>().eq(DistributionUserIncome::getDistributionUserId, id));
        List<String> collect = distributionUserIncomes.stream().map(DistributionUserIncome::getOrderNumber).collect(Collectors.toList());
        distributionUserIncomeMapper.updateDistributionUserIncomesBy(collect, distributionUser.getParentId(), DistributionUserIncomeStateEnum.INVALID.getValue(), DistributionUserIncomeTypeEnum.AWARD_TWO.getValue());
    }

    /**
     * 永久封禁收益清零，插入一条流水记录
     * @param id 分销员id
     */
//    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    void updateAmountByDistributionUserId(Long id) {
        DistributionUserWallet distributionUserWallet = distributionUserWalletMapper.selectOne(new LambdaQueryWrapper<DistributionUserWallet>().eq(DistributionUserWallet::getDistributionUserId, id));
//        插入一条流水记录  unsettled_amount = 0,settled_amount = 0,invalid_amount = 0,addup_amount = 0
        Double amount = 0d;
        DistributionUserWalletBill bill = new DistributionUserWalletBill();
        bill.setAddupAmount(amount);
        bill.setUnsettledAmount(amount);
        bill.setSettledAmount(amount);
        bill.setInvalidAmount(amount);
        bill.setRemarks("分销员被永久封禁，清空收益");
        bill.setRemarksEn("Distributors are permanently banned, emptying up earnings");
        bill.setCreateTime(new Date());
        bill.setType(0);
        bill.setWalletId(distributionUserWallet.getWalletId());
        distributionUserWalletBillService.save(bill);
        //将tz_distribution_user_wallet累计收益改为0
        distributionUserWalletMapper.updateAmountByDistributionUserId(id);
    }

    @Override
    public IPage<DistributionUser> getDistributionUserAchievementPage(Page page, DistributionUser distributionUser, String userMobile) {
        IPage<DistributionUser> userPage = distributionUserMapper.getDistributionUserAchievementPage(page, distributionUser, userMobile);
        if (BooleanUtil.isFalse(permission)) {
            for (DistributionUser record : userPage.getRecords()) {
                if (StrUtil.isNotBlank(record.getUserMobile())) {
                    record.setUserMobile(PhoneUtil.hideBetween(record.getUserMobile()).toString());
                }
                if (PrincipalUtil.isMobile(record.getNickName())) {
                    record.setNickName(PhoneUtil.hideBetween(record.getNickName()).toString());
                }
            }
        }
        return userPage;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void registerDistributionUser(DistributionUser distributionUser) {

        DistributionUser dbDistributionUser = getByUserIdAndShopId(distributionUser.getUserId(), distributionUser.getShopId());

        // 返回自增id
        Long distributionUserId;

        if (dbDistributionUser == null) {
            //存入分销员数据库
            distributionUserMapper.insert(distributionUser);

            distributionUserId = distributionUser.getDistributionUserId();

            //为这个分销员创建一个钱包
            DistributionUserWallet distributionUserWallet = new DistributionUserWallet();
            distributionUserWallet.setAddupAmount(0.0);
            distributionUserWallet.setSettledAmount(0.0);
            distributionUserWallet.setInvalidAmount(0.0);
            distributionUserWallet.setVersion(0);
            distributionUserWallet.setDistributionUserId(distributionUserId);
            distributionUserWallet.setUnsettledAmount(0.0);
            distributionUserWalletService.save(distributionUserWallet);
        } else {
            dbDistributionUser.setState(0);
            distributionUser.setDistributionUserId(dbDistributionUser.getDistributionUserId());
            distributionUserMapper.updateById(distributionUser);
            distributionUserId = dbDistributionUser.getDistributionUserId();
        }


        //创建申请记录该用户是否为本店分销员
        DistributionAuditing distributionAuditing = new DistributionAuditing();
        distributionAuditing.setAuditingTime(new Date());
        distributionAuditing.setShopId(distributionUser.getShopId());
        distributionAuditing.setDistributionUserId(distributionUserId);
        distributionAuditing.setParentDistributionUserId(distributionUser.getParentId());

        //符合条件，自动通过
        if (Objects.equals(distributionUser.getState(), DistributionUserStateEnum.NORMAL.getValue())) {
            distributionAuditing.setRemarks("系统判断自动通过审核");
            distributionAuditing.setState(1);
        } else {
            distributionAuditing.setState(0);
        }
        if (dbDistributionUser == null) {
            //存入申请记录
            distributionAuditingMapper.insert(distributionAuditing);
        } else {
            DistributionAuditing dbAuditing = distributionAuditingMapper.selectOne(new LambdaQueryWrapper<DistributionAuditing>().eq(DistributionAuditing::getDistributionUserId, distributionUserId));
            distributionAuditing.setAuditingId(dbAuditing.getAuditingId());
            distributionAuditingMapper.updateById(distributionAuditing);
        }


    }

    @Override
    public IPage<DistributionUserSimpleDto> getDistributionUserSimpleDtoByParentUserIdPage(Page page, Long parentDistributionUserId) {
        return distributionUserMapper.getDistributionUserSimpleDtoByParentUserIdPage(page, parentDistributionUserId);
    }


    @Override
    @Cacheable(cacheNames = "distribution_user_by_card_no", key = "#cardNo")
    public DistributionUser getByCardNo(String cardNo) {
        return distributionUserMapper.selectOne(new LambdaQueryWrapper<DistributionUser>().eq(DistributionUser::getCardNo, cardNo));
    }

    @Override
    @CacheEvict(cacheNames = "distribution_user_by_card_no", key = "#cardNo")
    public void removeCacheByCardNo(String cardNo) {

    }

    @Override
    public List<DistributionUser> getDistributionUserByIdCardNumberAndUserMobile(String identityCardNumber, String userMobile) {
        return distributionUserMapper.getDistributionUserByIdCardNumberAndUserMobile(identityCardNumber, userMobile);
    }

    @Override
    public List<DistributionUserInfoVO> getDistributionMyFriend(DistributionUser user, Integer userType) {
        if (userType.equals(DUserType.MY_FRIEND.getValue())) {
            // 获取二级佣金 == 我的好友推广的订单我的间接佣金
            List<DistributionUser> distributionUsers = distributionUserMapper.selectList(new LambdaQueryWrapper<DistributionUser>()
                    .eq(DistributionUser::getParentId, user.getDistributionUserId())
                    .eq(DistributionUser::getState, 1));
            if (CollUtil.isEmpty(distributionUsers)) {
                return new ArrayList<>();
            }
            return distributionUserIncomeMapper.getFriendInfo(user, distributionUsers, DistributionUserIncomeTypeEnum.AWARD_TWO.getValue());
        } else {
            //所有分销订单
            List<String> orderNumbers = distributionUserMapper.selectDistributionOrderId(user.getCardNo());
            if (CollUtil.isEmpty(orderNumbers)) {
                return new ArrayList<>();
            }
            List<DistributionUserBind> distributionUserBinds = distributionUserBindMapper.selectList(new LambdaQueryWrapper<DistributionUserBind>()
                    .eq(DistributionUserBind::getDistributionUserId, user.getDistributionUserId())
                    .eq(DistributionUserBind::getState, DistributionAudit.BIND_ONE.getValue()));
            List<String> userIds = distributionUserBinds.stream().map(DistributionUserBind::getUserId).collect(Collectors.toList());
            if (CollUtil.isEmpty(userIds)) {
                return new ArrayList<>();
            }
            return distributionUserIncomeMapper.selectIncomeInfo(userIds, orderNumbers, DistributionUserIncomeTypeEnum.AWARD_ONE.getValue(), user);
        }
    }
}
